package cn.com.easy.pay.alipay.wap.controller;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.alipay.union.config.AlipayUnionConfig;

import com.alipay.api.internal.util.AlipaySignature;

/* *
 功能：支付宝页面跳转同步通知页面
 版本：3.2
 日期：2011-03-17
 说明：
 以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
 该代码仅供学习和研究支付宝接口使用，只是提供一个参考。

 //***********页面功能说明***********
 该页面可在本机电脑测试
 可放入HTML等美化页面的代码、商户业务逻辑程序代码
 TRADE_FINISHED(表示交易已经成功结束，并不能再对该交易做后续操作);
 TRADE_SUCCESS(表示交易已经成功结束，可以对该交易做后续操作，如：分润、退款等);
 //********************************
 * */
public abstract class AlipayWapReturnBaseController {

	private Logger logger = LoggerFactory.getLogger(AlipayWapReturnBaseController.class);

	/**
	 * spring mvc跳转的jsp页面
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract String successReturnPagePath(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes,
			ReturnParam returnParam) throws BusinessException;

	/**
	 * 
	 * 异常跳转的页面<br/>
	 * 如果发生异常，请自行 查看 trade_status 的值 ，做相应处理,一般都是正确了才会跳到这个页面<br/>
	 * 如果发生异常加调这个方法前，会把错误信息放到 errorMsg中 modelMap.put("errorMsg",
	 * ex.getMessage());
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract String errorReturnPagePath(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes,
			ReturnParam returnParam);

	/**
	 * 功能：支付宝页面跳转同步通知页面 版本：3.2 日期：2011-03-17 说明：
	 * 以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
	 * 该代码仅供学习和研究支付宝接口使用，只是提供一个参考。
	 * 
	 * //***********页面功能说明*********** 该页面可在本机电脑测试 可放入HTML等美化页面的代码、商户业务逻辑程序代码
	 * TRADE_FINISHED(表示交易已经成功结束，并不能再对该交易做后续操作);
	 * TRADE_SUCCESS(表示交易已经成功结束，可以对该交易做后续操作，如：分润、退款等);
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月6日
	 */
	@RequestMapping("/return")
	public String returnPage(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes, ReturnParam returnParam) {
		try {
			// 获取支付宝GET过来反馈信息
			Map<String, String> params = new HashMap<String, String>();
			@SuppressWarnings("unchecked")
			Map<String, String[]> requestParams = request.getParameterMap();
			for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
				}
				// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
				// valueStr = new String(valueStr.getBytes("ISO-8859-1"),
				// "utf-8");
				params.put(name, valueStr);
			}
			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
			// 计算得出通知验证结果
			// boolean AlipaySignature.rsaCheckV1(Map<String, String> params,
			// String publicKey, String charset, String sign_type)
			AlipayUnionConfig alipayUnionConfig = getAlipayConfig();
			boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayUnionConfig.getAlipay_public_key(), AlipayUnionConfig.CHARSET, alipayUnionConfig.getSigntype());
			if (verify_result) {// 验证成功
				// ////////////////////////////////////////////////////////////////////////////////////////
				// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
				// if (StringUtils.equals(returnParam.getTrade_status(),
				// "TRADE_FINISHED") == true ||
				// StringUtils.equals(returnParam.getTrade_status(),
				// "TRADE_SUCCESS") == true) {
				// 判断该笔订单是否在商户网站中已经做过处理
				// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				// 如果有做过处理，不执行商户的业务程序
				return successReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
				// } else {
				// modelMap.put("errorMsg", "支付异常");
				// return errorReturnPagePath(modelMap, request, response,
				// redirectAttributes, returnParam);
				// }

				// 该页面可做页面美工编辑
				// response.getOutputStream().println("验证成功<br />");
				// ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——
				// ////////////////////////////////////////////////////////////////////////////////////////
			} else {
				// 该页面可做页面美工编辑
				throw new BusinessException("验证失败");
			}
		} catch (BusinessException ex) {
			logger.info("支付宝wap支付return业务代码异常", ex);
			modelMap.put("errorMsg", ex.getMessage());
			return errorReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
		} catch (Exception ex) {
			logger.info("支付宝wap支付return异常", ex);
			modelMap.put("errorMsg", "支付异常");
			return errorReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
		}

	}

	/**
	 * 支付宝配置参数
	 * 
	 * @return
	 * @author nibili 2017年4月6日
	 */
	public abstract AlipayUnionConfig getAlipayConfig();

	/**
	 * 支付宝返回时带的参数
	 * 
	 * @author nibili 2017年4月1日
	 * 
	 */
	public static class ReturnParam {

		/** 应用id */
		private String app_id;
		/** 商户网站唯一订单号 */
		private String out_trade_no;
		/** 支付宝交易号 */
		private String trade_no;
		/** 交易金额 */
		private String total_amount;
		/** 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 */
		private String seller_id;
		/** 支付结果状态，有两种是成功状态：TRADE_FINISHED， TRADE_SUCCESS */
		private String trade_status;
		/** 商品描述 */
		private String body;

		/**
		 * get 商户网站唯一订单号
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getOut_trade_no() {
			return out_trade_no;
		}

		/**
		 * set 商户网站唯一订单号
		 * 
		 * @param out_trade_no
		 * @author nibili 2017年4月27日
		 */
		public void setOut_trade_no(String out_trade_no) {
			this.out_trade_no = out_trade_no;
		}

		/**
		 * get 支付宝交易号
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getTrade_no() {
			return trade_no;
		}

		/**
		 * set 支付宝交易号
		 * 
		 * @param trade_no
		 * @author nibili 2017年4月27日
		 */
		public void setTrade_no(String trade_no) {
			this.trade_no = trade_no;
		}

		/**
		 * get 收款支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getSeller_id() {
			return seller_id;
		}

		/**
		 * set 收款支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字
		 * 
		 * @param seller_id
		 * @author nibili 2017年4月27日
		 */
		public void setSeller_id(String seller_id) {
			this.seller_id = seller_id;
		}

		/**
		 * get 支付结果状态，有两种是成功状态：TRADE_FINISHED，TRADE_SUCCESS
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getTrade_status() {
			return trade_status;
		}

		/**
		 * set 支付结果状态，有两种是成功状态：TRADE_FINISHED，TRADE_SUCCESS
		 * 
		 * @param trade_status
		 * @author nibili 2017年4月27日
		 */
		public void setTrade_status(String trade_status) {
			this.trade_status = trade_status;
		}

		/**
		 * get 商品描述
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getBody() {
			return body;
		}

		/**
		 * set 商品描述
		 * 
		 * @param body
		 * @author nibili 2017年4月27日
		 */
		public void setBody(String body) {
			this.body = body;
		}

		/**
		 * get 应用id
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getApp_id() {
			return app_id;
		}

		/**
		 * set 应用id
		 * 
		 * @param app_id
		 * @author nibili 2017年4月27日
		 */
		public void setApp_id(String app_id) {
			this.app_id = app_id;
		}

		/**
		 * get 交易金额
		 * 
		 * @return
		 * @author nibili 2017年4月27日
		 */
		public String getTotal_amount() {
			return total_amount;
		}

		/**
		 * set 交易金额
		 * 
		 * @param total_amount
		 * @author nibili 2017年4月27日
		 */
		public void setTotal_amount(String total_amount) {
			this.total_amount = total_amount;
		}

	}
}
